using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;

using SBPweb.Controls.Windows;
using SBPweb.Themes.Windows;
using SBPweb.Themes.Windows.Skins;

namespace SBPweb.Controls.Windows.Editors
{
	/// <summary>
	/// Class of CloseButton
	/// </summary>
	[ToolboxBitmap(typeof(System.Windows.Forms.Button))]
	public partial class CloseButton : System.Windows.Forms.Button, ISkinnable
	{
		#region Private members

		private bool mUseDefaultSkin = true;
		private Skin mSkin;
		private Margin mSizingMargin;
		private SBPweb.Themes.Windows.Skins.Size mMinSize;
		private MouseEventState mMState = MouseEventState.None;
		

		#endregion

		#region Constructor logic

		public CloseButton()
		{
			//InitializeCmponent();

			InitializeMargins();
			InitializeMinSize();

			this.Size = new System.Drawing.Size((int)mMinSize.MinSize.Width, (int)mMinSize.MinSize.Height);
			
			SetStyle(); 
			RegisterEventHandlers();
		}

		public CloseButton(Skin skin)
		{
			mSkin = skin;

			InitializeComponent();
			
			InitializeMargins();
			InitializeMinSize();

			this.Size = new System.Drawing.Size((int)mMinSize.MinSize.Width, (int)mMinSize.MinSize.Height);

			SetStyle();
			RegisterEventHandlers();
		}

		private void SetStyle()
		{
			base.SetStyle(ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor, true);
		}

		private void RegisterEventHandlers()
		{
			this.MouseEnter += new EventHandler(this_MouseEnter);
			this.MouseLeave += new EventHandler(this_MouseLeave);
			this.MouseDown += new MouseEventHandler(this_MouseDown);
			this.MouseUp += new MouseEventHandler(this_MouseUp);
			this.MouseHover += new EventHandler(this_MouseHover);
			DefaultLookAndFeel.OnSkinChanged += new EventHandler(DefaultLookAndFeel_OnSkinChanged);
		}

		private void InitializeMargins()
		{
			if (Skin == null)
			{
				mSizingMargin = new Margin();
				//mContentMargin = new Margin();
			}
			else
			{
				mSizingMargin = new Margin(Skin.SelectSingleNode("Elements/Button/Image/SizingMargins"));
				//mContentMargin = new Margin(Skin.SelectSingleNode("Elements/Button/ContentMargins"));
			}
		}

		private void InitializeMinSize()
		{

			if (Skin == null)
			{
				mMinSize= new SBPweb.Themes.Windows.Skins.Size();
			}
			else
			{
				mMinSize = new SBPweb.Themes.Windows.Skins.Size(Skin.SelectSingleNode("Elements/Button/Size"));
			}

		}
		#endregion

		#region Custom draw
		
		protected override void OnPaint(PaintEventArgs e)
		{

			if (Skin == null)
			{
				base.OnPaint(e);
				this.MinimumSize = new System.Drawing.Size((int)mMinSize.MinSize.Width,(int)mMinSize.MinSize.Height);
				return;
			}

			base.OnPaintBackground(e);

			//this.Size = new System.Drawing.Size((int)mMinSize.MinSize.Width, (int)mMinSize.MinSize.Height);

			System.Drawing.Image img = Skin.GetImageFromBitmapResource(Skin.KeyPrefix + "editors.closebutton.png");
			bool verticalLayout = false;
			if (Skin.SelectSingleNode("Elements/CloseButton/Image").Attributes["Layout"] != null)
			{
				if (Skin.SelectSingleNode("Elements/CloseButton/Image").Attributes["Layout"].Value.ToLower() == "vertical")
				{
					verticalLayout = true;
				}
			}

			int imgCount = 4;
			int imgWidth = img.Width - 1;
			int imgHeight = (Int32)(img.Height / imgCount);
			int imgTop;
			int imgLeft;


			if (!verticalLayout)
			{
				imgWidth = (Int32)(img.Width / imgCount);
				imgHeight = img.Height;
				imgTop = 0;

				switch (mMState)
				{
					default:
					case MouseEventState.None:
						if (this.Enabled)
						{
							imgLeft = 0;
						}
						else
						{
							imgLeft = 3 * imgWidth;
						}
						break;
					case MouseEventState.OnHover:
						imgLeft = 1 * imgWidth;
						break;
					case MouseEventState.OnDown:
						if (this.Enabled)
						{
							imgLeft = 2 * imgWidth;
						}
						else
						{
							imgLeft = 4 * imgWidth;
						}
						break;
				}
			}
			else
			{
				imgLeft = 0;
				switch (mMState)
				{
					default:
					case MouseEventState.None:
						if (this.Enabled)
						{
							imgTop = 0;
						}
						else
						{
							imgTop = 3 * imgHeight;
						}
						break;
					case MouseEventState.OnHover:
						imgTop = 1 * imgHeight;
						break;
					case MouseEventState.OnDown:
						if (this.Enabled)
						{
							imgTop = 2 * imgHeight;
						}
						else
						{
							imgTop = 4 * imgHeight;
						}
						break;
				}
			}

			#region Image parts
			Rectangle iLT = new Rectangle(imgLeft, imgTop, mSizingMargin.Left, mSizingMargin.Top);
			Rectangle iT = new Rectangle(imgLeft + mSizingMargin.Left, imgTop, imgWidth - mSizingMargin.Horizontal, mSizingMargin.Top);
			Rectangle iRT = new Rectangle(imgLeft + imgWidth - mSizingMargin.Right, imgTop, mSizingMargin.Right, mSizingMargin.Top);
			Rectangle iLM = new Rectangle(imgLeft, imgTop + mSizingMargin.Top, mSizingMargin.Left, (imgHeight - 1) - mSizingMargin.Vertical);
			Rectangle iM = new Rectangle(imgLeft + mSizingMargin.Left, imgTop + mSizingMargin.Top, imgWidth - mSizingMargin.Horizontal, (imgHeight - 1) - mSizingMargin.Vertical);
			Rectangle iRM = new Rectangle(imgLeft + imgWidth - mSizingMargin.Right, imgTop + mSizingMargin.Top, mSizingMargin.Right, (imgHeight - 1) - mSizingMargin.Vertical);
			Rectangle iLB = new Rectangle(imgLeft, imgTop + imgHeight - mSizingMargin.Bottom, mSizingMargin.Left, mSizingMargin.Bottom);
			Rectangle iB = new Rectangle(imgLeft + mSizingMargin.Left, imgTop + imgHeight - mSizingMargin.Bottom, imgWidth - mSizingMargin.Horizontal, mSizingMargin.Bottom);
			Rectangle iRB = new Rectangle(imgLeft + imgWidth - mSizingMargin.Right, imgTop + imgHeight - mSizingMargin.Bottom, mSizingMargin.Right, mSizingMargin.Bottom);
			#endregion

			#region Window parts
			Rectangle tLT = new Rectangle(this.ClientRectangle.Left, this.ClientRectangle.Top, mSizingMargin.Left, mSizingMargin.Top);
			Rectangle tT = new Rectangle(this.ClientRectangle.Left + mSizingMargin.Left, this.ClientRectangle.Top, this.ClientRectangle.Width - mSizingMargin.Horizontal, mSizingMargin.Top);
			Rectangle tRT = new Rectangle(this.ClientRectangle.Right - mSizingMargin.Right, this.ClientRectangle.Top, mSizingMargin.Right, mSizingMargin.Top);
			Rectangle tLM = new Rectangle(this.ClientRectangle.Left, this.ClientRectangle.Top + mSizingMargin.Top, mSizingMargin.Left, this.ClientRectangle.Height - mSizingMargin.Vertical);
			Rectangle tM = new Rectangle(this.ClientRectangle.Left + mSizingMargin.Left, this.ClientRectangle.Top + mSizingMargin.Top, this.ClientRectangle.Width - mSizingMargin.Horizontal, this.ClientRectangle.Height - mSizingMargin.Vertical);
			Rectangle tRM = new Rectangle(this.ClientRectangle.Right - mSizingMargin.Right, this.ClientRectangle.Top + mSizingMargin.Top, mSizingMargin.Right, this.ClientRectangle.Height - mSizingMargin.Vertical);
			Rectangle tLB = new Rectangle(this.ClientRectangle.Left, this.ClientRectangle.Bottom - mSizingMargin.Bottom, mSizingMargin.Left, mSizingMargin.Bottom);
			Rectangle tB = new Rectangle(this.ClientRectangle.Left + mSizingMargin.Left, this.ClientRectangle.Bottom - mSizingMargin.Bottom, this.ClientRectangle.Width - mSizingMargin.Horizontal, mSizingMargin.Bottom);
			Rectangle tRB = new Rectangle(this.ClientRectangle.Right - mSizingMargin.Right, this.ClientRectangle.Bottom - mSizingMargin.Bottom, mSizingMargin.Right, mSizingMargin.Bottom);
			#endregion

			#region Drawing
			e.Graphics.DrawImage(img, tLT, iLT, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tT, iT, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tRT, iRT, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tLM, iLM, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tM, iM, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tRM, iRM, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tLB, iLB, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tB, iB, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tRB, iRB, GraphicsUnit.Pixel);

			#endregion
			
			//this.MinimumSize = new System.Drawing.Size((int)mMinSize.MinSize.Width, (int)mMinSize.MinSize.Height);

			DrawGlyph(e);
		}

		private void DrawGlyph(PaintEventArgs e)
		{
			System.Drawing.Image img = Skin.GetImageFromBitmapResource(Skin.KeyPrefix + "editors.closebutton_glyph.png");
			bool verticalLayout = false;
			if (Skin.SelectSingleNode("Elements/CloseButton/Glyph").Attributes["Layout"] != null)
			{
				if (Skin.SelectSingleNode("Elements/CloseButton/Glyph").Attributes["Layout"].Value.ToLower() == "vertical")
				{
					verticalLayout = true;
				}
			}

			int imgCount = 4;
			int imgWidth = img.Width;
			int imgHeight = (Int32)(img.Height / imgCount);
			int imgTop;
			int imgLeft;

			if (!verticalLayout)
			{
				imgWidth = (Int32)(img.Width / imgCount);
				imgHeight = img.Height;
				imgTop = 0;

				switch (mMState)
				{
					default:
					case MouseEventState.None:
						if (this.Enabled)
						{
							imgLeft = 0;
						}
						else
						{
							imgLeft = 3 * imgWidth;
						}
						break;
					case MouseEventState.OnHover:
						imgLeft = 1 * imgWidth;
						break;
					case MouseEventState.OnDown:
						if (this.Enabled)
						{
							imgLeft = 2 * imgWidth;
						}
						else
						{
							imgLeft = 4 * imgWidth;
						}
						break;
				}
			}
			else
			{
				imgLeft = 0;
				switch (mMState)
				{
					default:
					case MouseEventState.None:
						if (this.Enabled)
						{
							imgTop = 0;
						}
						else
						{
							imgTop = 3 * imgHeight;
						}
						break;
					case MouseEventState.OnHover:
						imgTop = 1 * imgHeight;
						break;
					case MouseEventState.OnDown:
						if (this.Enabled)
						{
							imgTop = 2 * imgHeight;
						}
						else
						{
							imgTop = 4 * imgHeight;
						}
						break;
				}
			}

			Rectangle rect = new Rectangle(imgLeft, imgTop, imgWidth, imgHeight);

			Point target = new Point((int)Math.Round((e.ClipRectangle.Width - rect.Width) / 2.0,MidpointRounding.AwayFromZero),(int)Math.Round((e.ClipRectangle.Height - rect.Height)/ 2.0, MidpointRounding.AwayFromZero));

			e.Graphics.DrawImage(img, target.X, target.Y, rect, GraphicsUnit.Pixel);

			this.MinimumSize = new System.Drawing.Size((int)mMinSize.MinSize.Width, (int)mMinSize.MinSize.Height);
		}


		protected override void OnPaintBackground(PaintEventArgs e)
		{
			base.OnPaintBackground(e);
		}
		#endregion

		#region Events
		void this_MouseEnter(object sender, EventArgs e)
		{
			mMState = MouseEventState.OnHover;
			this.Invalidate();
		}

		void this_MouseUp(object sender, MouseEventArgs e)
		{
			if (e.X < 0 || e.X > this.Width || e.Y < 0 || e.Y > this.Height)
			{
				mMState = MouseEventState.None;
			}
			else
			{
				mMState = MouseEventState.OnHover;
			}
			
			this.Invalidate();
		}

		void this_MouseDown(object sender, MouseEventArgs e)
		{
			mMState = MouseEventState.OnDown;
			this.Invalidate();
		}

		void this_MouseLeave(object sender, EventArgs e)
		{
			mMState = MouseEventState.None;
			this.Invalidate();
		}

		void this_MouseHover(object sender, EventArgs e)
		{
			mMState = MouseEventState.OnHover;
		}

		void DefaultLookAndFeel_OnSkinChanged(object sender, EventArgs e)
		{
			InitializeMargins();
			InitializeMinSize();
		}

		#endregion

		#region ISkinnable Members

		/// <summary>
		/// Use default skin?
		/// </summary>
		[Category("Look && feel")]
		public bool UseDefaultSkin
		{
			get
			{
				return mUseDefaultSkin;
			}
			set
			{
				mUseDefaultSkin = value;
				Invalidate();
			}
		}

		/// <summary>
		/// Used skin
		/// </summary>
		[Category("Look && feel")]
		public Skin Skin
		{
			get
			{
				if (this.UseDefaultSkin)
				{
					
					return DefaultLookAndFeel.Skin;
				}
				
				return mSkin;
			}
			set
			{
				mSkin = value;
				Invalidate();
			}
		}

		#endregion
	}
}
